package com.jinhua.huaojcodesandbox;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.jinhua.huaojcodesandbox.model.ExecuteCodeRequest;
import com.jinhua.huaojcodesandbox.model.ExecuteCodeResponse;
import com.jinhua.huaojcodesandbox.model.ExecuteMessage;
import com.jinhua.huaojcodesandbox.model.JudgeInfo;
import com.jinhua.huaojcodesandbox.model.enums.QuestionSubmitJudgeInfoMessageEnum;
import com.jinhua.huaojcodesandbox.model.enums.QuestionSubmitStateEnum;
import com.jinhua.huaojcodesandbox.utils.ProcessUtils;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;


public class JavaNativeCodeSandBoxOld implements CodeSandBox {

    private static final String GLOBAL_CODE_DIR_NAME = "tmpCode";
    private static final String CODE_CLASS_NAME = "Main.java";
    private static final long TIME_OUT = 5000;
    private static final String SECURITY_PATH = "/home/huaoj/code/huaoj/src/main/resources/security";
    private static final String SECURITY_CLASS_NAME = "DefaultSecurityManager";
//    使用黑名单限制用户执行命令  无法找到所有需要限制的命令
//    private static final List<String > blackList = Arrays.asList("Files", "exec");
//    private static final WordTree WORD_TREE = new WordTree();
//
//    static {
//        //        添加校验代码
//        WORD_TREE.addWords(blackList);
//
//    }


    @Override
    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest)  {
        // 1.获取executeCodeRequest中的数据
        String code = executeCodeRequest.getCode();
        List<String> inputList = executeCodeRequest.getInputList();
        String language = executeCodeRequest.getLanguage();


        // 2. 创建代码执行文件
        //获取当前系统的根目录
        String userDir = System.getProperty("user.dir");
//        使用File.separator适配不同系统（win、linux）
//        在根目录下创建存放代码的全局代码目录
        String globalCodePathName = userDir + File.separator + GLOBAL_CODE_DIR_NAME;
//        判断全局代码目录是否存在 否则新建
        if (!FileUtil.exist(globalCodePathName)) {
            FileUtil.mkdir(globalCodePathName);
        }
//        因为用户的文件都将保存为名字为Main.java的文件无法在同一目录下存放需要分级
//        使用uuid生成目录名称并组合为路径
        String userCodeParentPath = globalCodePathName + File.separator + UUID.randomUUID();
//        生成代码文件路径
        String userCodePath = userCodeParentPath + File.separator + CODE_CLASS_NAME;
//        将代码写入到指定位置
        File userCodeFile = FileUtil.writeString(code, userCodePath, StandardCharsets.UTF_8);


        //        3.编译执行
//        生成编译用户代码文件cmd命令
        String compileCMD = String.format("javac -encoding utf8 %s", userCodePath);
        Process compilerProcess = null;
        try {
            compilerProcess = Runtime.getRuntime().exec(compileCMD);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

//        使用进程工具类进行执行编译cmd命令
        ExecuteMessage compileExecuteMessage = null;
        try {
            compileExecuteMessage = ProcessUtils.getProcessRunMessage(compilerProcess,"编译");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

//        4.执行用户代码 并获取输出列表
        List<ExecuteMessage> executeMessageList = new ArrayList<>();
        String runMessage = null;
        ExecuteCodeResponse executeCodeResponse = new ExecuteCodeResponse();
        executeCodeResponse.setState(QuestionSubmitStateEnum.ACCOMPLISH.getValue());
        long maxTime = 0l;

        for (String input : inputList) {
//            String runCMD = String.format("java -Dfile.encoding=UTF-8 -cp %s Main", userCodeParentPath);
//            内存控制
//            cp 地址结束符windows为; linux为:
//            windows执行命令
//            String runCMD = String.format("java -Xmx1024m -Dfile.encoding=GBK -cp \"%s:%s\"  -Djava.security.manager=%s Main", userCodeParentPath,SECURITY_PATH, SECURITY_CLASS_NAME);
//            linux执行命令
            String runCMD = String.format("java -Xmx1024m -Dfile.encoding=GBK -cp %s:%s  -Djava.security.manager=%s Main", userCodeParentPath,SECURITY_PATH, SECURITY_CLASS_NAME);
//            String runCMD = String.format("java -Xmx256m  -Dfile.encoding=UTF-8 -cp %s Main", userCodeParentPath);
            Process executeProcess;
            try {
                executeProcess = Runtime.getRuntime().exec(runCMD);
//                超时控制  todo 程序十秒才能结束
//                new Thread(() -> {
//                    try {
//                        Thread.sleep(TIME_OUT);
//                        if (executeProcess != null) {
//                            System.out.println("超时");
//                            executeProcess.destroy();
//                            System.out.println(executeProcess);
//                        }
//                    } catch (InterruptedException e) {
//                        throw new RuntimeException(e);
//                    }
//                }).start();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            ExecuteMessage runExecuteMessage = ProcessUtils.runInteractProcess(executeProcess, input,"运行");
            executeProcess.destroy();

            long time = runExecuteMessage.getTime();
            if (time > maxTime) {
                maxTime = time;
            }
            System.out.println(runExecuteMessage);
//            int runExitValue = runExecuteMessage.getExitValue();
//            if (runExitValue == 0) {
//                runMessage = runExecuteMessage.getMessage();
//                System.out.println(runMessage);
//                executeMessageList.add(runExecuteMessage);
//
//            } else {
//                runMessage = runExecuteMessage.getErrorMessage();
//                executeCodeResponse.setState(QuestionSubmitStateEnum.FAIL.getValue());
//                System.out.println(runMessage);
//            }
        }


        List<String> outputList = executeMessageList.stream().map(item -> {
            if (item.getExitValue() == 0) {
                return item.getMessage();
            } else {
                return item.getErrorMessage();
            }
        }).collect(Collectors.toList());
        executeCodeResponse.setOutputList(outputList);
        JudgeInfo judgeInfo = new JudgeInfo();
        judgeInfo.setMessage(QuestionSubmitJudgeInfoMessageEnum.ACCEPTED.getValue());
        judgeInfo.setTime(maxTime);
//  todo    比较麻烦暂不处理

//        judgeInfo.setMemory();

//        5.清楚文件
        if (userCodeFile.getParentFile() != null) {
            boolean del = FileUtil.del(userCodeParentPath);
            System.out.println("删除" + (del ? "成功" : "失败"));
        }
//        错误处理


        executeCodeResponse.setExcuteInfo(judgeInfo);


        return executeCodeResponse;
    }
}


